int multiplex_fdm(unsigned char *c, const int c_size, const unsigned char *a, const int a_len, const unsigned char *b, const int b_len) {
    int max_len = a_len > b_len ? a_len : b_len;
    if (c_size < 8 + max_len) return -1;
    for (int i = 0; i < 4; i++) c[i] = (a_len >> (8 * i)) & 0xFF;
    for (int i = 0; i < 4; i++) c[4 + i] = (b_len >> (8 * i)) & 0xFF;
    int j = 8;
    for (int i = 0; i < max_len; i++) {
        unsigned char a_val = (i < a_len) ? a[i] : 0;
        unsigned char b_val = (i < b_len) ? b[i] : 0;
        c[j++] = a_val + 2 * b_val;
    }
    return 0;
}

int demultiplex_fdm(unsigned char *a, const int a_size, unsigned char *b, const int b_size, const unsigned char *c, const int c_len) {
    int a_len = 0, b_len = 0;
    for (int i = 0; i < 4; i++) a_len |= (c[i] << (8 * i));
    for (int i = 0; i < 4; i++) b_len |= (c[4 + i] << (8 * i));
    int actual_a_len = a_len < a_size ? a_len : a_size;
    int actual_b_len = b_len < b_size ? b_len : b_size;
    int max_len = a_len > b_len ? a_len : b_len;
    int index = 8;
    for (int i = 0; i < max_len; i++) {
        if (i < actual_a_len) a[i] = (c[index] == 1 || c[index] == 3) ? 1 : 0;
        if (i < actual_b_len) b[i] = (c[index] == 2 || c[index] == 3) ? 1 : 0;
        index++;
    }
    return 0;
}